/*
 * @Author       : Bing Chen chenbing@iocharger.com
 * @Date         : 2024-05-20 22:39:54
 * @LastEditors  : Bing Chen chenbing@iocharger.com
 * @LastEditTime : 2025-03-17 09:32:23
 * @FilePath     : \openchaoji-corelib\evcc\gbt27930\OpenChaoJi_evcc_gbt27930_def.h
 * @Description  : 本文件声明EVCC的system模块的通用状态机处理逻辑
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef __OPEN_CHAOJI_EVCC_GBT27930_DEF_H__
#define __OPEN_CHAOJI_EVCC_GBT27930_DEF_H__

#include "../../shared/include/OpenChaoJi_shared.h"

struct OpenChaoJi_evcc_context;
struct OpenChaoJi_evcc_context_create_info;
struct OpenChaoJi_evcc_context_status;
struct OpenChaoJi_evcc_app_start_parameter;

/**
 * 每个状态的前置/后置/循环动作函数
 * 状态对应于27930里面的B类系统S0/S1/S2等, A类系统对应附录A中流程图的每个判断分支步骤
 * 前置,后置动作不影响流程逻辑, 所以返回void
 * 循环动作可能影响状态跳转, 需要返回下一个状态
*/
struct OpenChaoJi_evcc_module_status
{
    /**
     * 每个状态预定义一个全局唯一的id, 采用FD
     * 高16位为模块号, 低16位为该模块的子状态
    */
    const int module_status_id;
    /**
     * 子状态名字, 调试用
     */
    const char * name;

    void (*prev_func)(struct OpenChaoJi_evcc_context * context);
    void (*post_func)(struct OpenChaoJi_evcc_context * context);

    /* 返回值为全局定义的唯一id module_status_id */
    int  (*loop_func)(struct OpenChaoJi_evcc_context * context);
};

/**
 * 定义27930的各个模块的状态列表 (一个模块由若干个状态构成)
 * B类系统沿用27930定义的标准模块名称, 为了便于理解, 建议把14.5章版本协商引入为一个独立模块
 * A类系统建议按照章节9的方式, 分为低压辅助上电, 充电握手, 参数配置, 充电阶段, 结束阶段几个模块, 便于理解
*/
struct OpenChaoJi_evcc_module
{
    int module_id;

    /**
     * B类系统需要根据协商结果查找下一个FDC, 初始声明, 方便后续查找
     */
#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
    enum OpenChaoJi_gbt27930_b_FCType fc_type;
    unsigned char fdc_type;
#endif

    /**
     * 子状态名字, 调试用
     */
    const char * name;

    /**
     * 本模块的各个状态
    */
    const struct OpenChaoJi_evcc_module_status * status_array;
    int status_array_len;
};

/**
 * 定义27930的A/B两个系统,一个系统由多个模块构成
 * 1. A类系统模块和状态都是固定的, 创建上下文的时候生成固定的数组
 * 2. B类系统模块是可变的, 部分是必须的模块, 部分是选配的模块, 需要在初始化上下文的时候指定装载哪些模块
*/
struct OpenChaoJi_evcc_gbt27930_system
{
    /**
     * 名称, 用于调试
     */
    const char * name;

    /**
     * B类系统模块可变, 需要在createInfo中传递支持情况, 根据支持情况来决定初始化多少模块
     * A类系统固定, 可以考虑使用常数组, 多个EVCC可以公用来节省空间
    */
    const struct OpenChaoJi_evcc_module ** module_array;
    int module_array_len;

    /**
     * 通用子模块处理, 即跨越一般功能模块的一些全局功能的处理. 例如链路检测, 连接检测等
     * 由于连接检测需要快速响应, 厂家底层实现时可以考虑通过中断等方式触发后立即调用service方法来触发处理流程, 而不必等到定时处理
    */
    int  (*sub_module_func)(struct OpenChaoJi_evcc_context * context);

    /**
     * 收发数据的通用处理方法
     * 收是在执行所有system操作前统一执行, 用于同步对端状态
     * 发是在执行所有system后统一执行, 用于把本方状态同步给对端
    */
    void (*data_read_func)(struct OpenChaoJi_evcc_context * context);
    void (*data_write_func)(struct OpenChaoJi_evcc_context * context);

    /**
     * 启停充电/获取充电等方法, 供App调用
    */
    int (*app_start_func)(struct OpenChaoJi_evcc_context * context, struct OpenChaoJi_evcc_app_start_parameter * app_start_parameter);
    int (*app_stop_func)(struct OpenChaoJi_evcc_context * context);
    int  (*app_get_status_func)(struct OpenChaoJi_evcc_context * context, struct OpenChaoJi_evcc_context_status * status);
};

/**
 * @brief: 根据module_status_id 查找模块
 * @param {OpenChaoJi_evcc_gbt27930_system *} evcc_gbt27930_system
 * @param {int} module_status_id
 * @return {*} 模块对象指针
 */
const struct OpenChaoJi_evcc_module * OpenChaoJi_evcc_service_find_module(struct OpenChaoJi_evcc_gbt27930_system * evcc_gbt27930_system, const int module_status_id);

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)
/**
 * @brief: B类系统根据FC 和 FDC 查找模块
 * @param {OpenChaoJi_evcc_gbt27930_system *} evcc_gbt27930_system
 * @param {enum OpenChaoJi_gbt27930_b_FCType} fc_type
 * @param {uint8_t} fdc_type
 * @return {*} 模块对象指针
 */
const struct OpenChaoJi_evcc_module * OpenChaoJi_evcc_service_find_module_by_fdc(struct OpenChaoJi_evcc_gbt27930_system * evcc_gbt27930_system, enum OpenChaoJi_gbt27930_b_FCType fc_type, uint8_t fdc_type);
#endif

/**
 * @brief: 根据module_status_id 查找 状态
 * @param {OpenChaoJi_evcc_gbt27930_system *} evcc_gbt27930_system
 * @param {int} module_status_id
 * @return {*} 状态对象指针
 */
const struct OpenChaoJi_evcc_module_status * OpenChaoJi_evcc_service_find_status(struct OpenChaoJi_evcc_gbt27930_system * evcc_gbt27930_system, const int module_status_id);

#endif
